home *** CD-ROM | disk | FTP | other *** search
/ PD Collection CD 1 / PD Collection CD 1.iso / programer2 / icon / Source / Icont / C / Lmem < prev    next >
Encoding:
Text File  |  1990-07-20  |  13.6 KB  |  602 lines

  1. /*
  2.  * lmem.c -- memory initialization and allocation; also parses arguments.
  3.  */
  4.  
  5. #include "../h/config.h"
  6. #include "general.h"
  7. #include "tproto.h"
  8. #include "globals.h"
  9. #include "link.h"
  10.  
  11. /*
  12.  * The following code is operating-system dependent [@lmem.01].  It includes
  13.  *  files that are system dependent.
  14.  */
  15.  
  16. #if PORT
  17.    /* nothing is needed */
  18. Deliberate Syntax Error
  19. #endif                    /* PORT */
  20.  
  21. #if AMIGA || ARM || ATARI_ST || HIGHC_386 || MACINTOSH || VMS
  22.    /* nothing is needed */
  23. #endif                    /* AMIGA || ATARI_AT || HIGHC_386 ... */
  24.  
  25. #if MSDOS
  26. #if MICROSOFT
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #endif                    /* MICROSOFT */
  30. #if TURBO
  31. #include <sys/stat.h>
  32. #endif                    /* TURBO */
  33. #endif                    /* MSDOS */
  34.  
  35. #if MVS || VM
  36. #if SASC
  37. #include <fcntl.h>
  38. #else                    /* SASC */
  39. #include <file.h>
  40. #endif                    /* SASC */
  41. #endif                    /* MVS || VM */
  42.  
  43. #if OS2
  44. #if MICROSOFT
  45. #include <sys/types.h>
  46. #include <sys/stat.h>
  47. #endif                    /* MICROSOFT */
  48. #endif                    /* OS2 */
  49.  
  50. #if UNIX
  51. #ifndef ATT3B
  52. #ifdef CRAY
  53. #define word word_fubar
  54. #include <sys/types.h>
  55. #include <sys/stat.h>
  56. #undef word
  57. #else                    /* CRAY */
  58. #include <sys/types.h>
  59. #include <sys/stat.h>
  60. #endif                    /* CRAY */
  61. #endif                    /* ATT3B */
  62. #endif                    /* UNIX */
  63.  
  64. /*
  65.  * End of operating-system specific code.
  66.  */
  67.  
  68. /*
  69.  * Prototypes.
  70.  */
  71.  
  72. hidden struct    lfile *alclfile    Params((char *name));
  73. hidden int    canread        Params((char *file));
  74. hidden int    trypath        Params((char *name,char *file));
  75.  
  76. #ifdef MultipleRuns
  77. hidden novalue    freelfile    Params((struct lfile *p));
  78. #endif                    /* MultipleRuns */
  79.  
  80. /*
  81.  * Memory initialization
  82.  */
  83.  
  84. struct gentry **lghash;        /* hash area for global table */
  85. struct ientry **lihash;        /* hash area for identifier table */
  86. struct fentry **lfhash;        /* hash area for field table */
  87.  
  88. struct lentry *lltable;        /* local table */
  89. struct gentry *lgtable;        /* global table */
  90. struct centry *lctable;        /* constant table */
  91. struct ientry *litable;        /* identifier table */
  92. struct fentry *lftable;        /* field table headers */
  93. struct rentry *lrtable;        /* field table record lists */
  94. struct ipc_fname *fnmtbl;    /* table associating ipc with file name */
  95. struct ipc_line *lntable;    /* table associating ipc with line number */
  96.  
  97. char *lsspace;            /* string space */
  98. word *labels;            /* label table */
  99. char *codeb;            /* generated code space */
  100.  
  101. struct gentry *lgfree;        /* free pointer for global table */
  102. struct ientry *lifree;        /* free pointer for identifier table */
  103. struct fentry *lffree;        /* free pointer for field table headers */
  104. struct rentry *lrfree;        /* free pointer for field table record lists */
  105. struct ipc_fname *fnmfree;    /* free pointer for ipc/file name table */
  106. struct ipc_line *lnfree;    /* free pointer for ipc/line number table */
  107. char *lsfree;            /* free pointer for string space */
  108. char *codep;            /* free pointer for code space */
  109.  
  110. char *lsend;            /* pointer to end of string space */
  111.  
  112. static char *ipath;        /* path for iconx */
  113.  
  114. #ifdef MultipleRuns
  115. extern word pc;
  116. extern int fatals;
  117. extern int nlflag;
  118. extern int lstatics;
  119. extern int nfields;
  120. #endif                    /* MultipleRuns */
  121.  
  122. /*
  123.  * linit - scan the command line arguments and initialize data structures.
  124.  */
  125. novalue linit()
  126.    {
  127.    struct gentry **gp;
  128.    struct ientry **ip;
  129.    struct fentry **fp;
  130.  
  131.    llfiles = NULL;        /* Zero queue of files to link. */
  132.  
  133. #ifdef EnvVars
  134.    ipath = getenv(IPATH);
  135. #else                    /* EnvVars */
  136.    ipath = NULL;
  137. #endif                    /* EnvVars */
  138.  
  139.    if (ipath == NULL)
  140.  
  141. /*
  142.  * The following code is operating-system dependent [@lmem.02].  Set default for
  143.  *  IPATH.
  144.  */
  145.  
  146. #if PORT
  147.    /* something is needed */
  148. Deliberate Syntax Error
  149. #endif                    /* PORT */
  150.  
  151. #if ARM
  152.     ipath = "Icon: Lib:Icon.";
  153. #endif                    /* ARM */
  154.  
  155. #if AMIGA
  156.    /*
  157.     * There is no environment, so set ipath to the null string. The
  158.     *  current directory is searched anyway and there is no symbol
  159.     *  to force current path search.
  160.     */
  161.       ipath = "";
  162. #endif                    /* AMIGA */
  163.  
  164. #if ATARI_ST || UNIX
  165.       ipath = ".";
  166. #endif                    /* ATARI_ST || UNIX */
  167.  
  168. #if HIGHC_386 || MSDOS || OS2
  169.       ipath = ";";
  170. #endif                    /* HIGHC_386 || MSDOS || OS2 */
  171.  
  172. #if MACINTOSH
  173. #if MPW || LSC
  174.       ipath = ":";
  175. #endif                    /* MPW || LSC */
  176. #endif                    /* MACINTOSH */
  177.  
  178. #if MVS || VM
  179.       ipath = "";
  180. #endif                    /* MVS || VS */
  181.  
  182. #if VMS
  183.       ipath = "[]";
  184. #endif                    /* VMS */
  185.  
  186. /*
  187.  * End of operating-system specific code.
  188.  */
  189.  
  190.    /*
  191.     * Allocate the various data structures that are used by the linker.
  192.     */
  193.    lghash   = (struct gentry **) tcalloc(ghsize, sizeof(struct gentry *));
  194.    lihash   = (struct ientry **) tcalloc(ihsize, sizeof(struct ientry *));
  195.    lfhash   = (struct fentry **) tcalloc(fhsize, sizeof(struct fentry *));
  196.  
  197.    lltable  = (struct lentry *) tcalloc(lsize, sizeof(struct lentry));
  198.    lctable  = (struct centry *) tcalloc(csize, sizeof(struct centry));
  199.  
  200.    lffree = lftable  = (struct fentry *) tcalloc(fsize, sizeof(struct fentry));
  201.    lgfree = lgtable  = (struct gentry *) tcalloc(gsize, sizeof(struct gentry));
  202.    lifree = litable  = (struct ientry *) tcalloc(isize, sizeof(struct ientry ));
  203.    lnfree = lntable  = (struct ipc_line*)tcalloc(nsize,sizeof(struct ipc_line));
  204.    lrfree = lrtable  = (struct rentry *) tcalloc(rsize, sizeof(struct rentry));
  205.  
  206.    lsfree = lsspace = (char *) tcalloc(stsize, sizeof(char));
  207.    lsend = lsspace + stsize - 1;
  208.  
  209.    fnmtbl = (struct ipc_fname *) tcalloc(fnmsize, sizeof(struct ipc_fname));
  210.    fnmfree = fnmtbl;
  211.  
  212.    labels  = (word *) tcalloc(maxlabels, sizeof(word));
  213.    codep = codeb = (char *) tcalloc(maxcode, 1);
  214.  
  215.    /*
  216.     * Zero out the hash tables.
  217.     */
  218.    for (gp = lghash; gp < &lghash[ghsize]; gp++)
  219.       *gp = NULL;
  220.    for (ip = lihash; ip < &lihash[ihsize]; ip++)
  221.       *ip = NULL;
  222.    for (fp = lfhash; fp < &lfhash[fhsize]; fp++)
  223.       *fp = NULL;
  224.  
  225. #ifdef MultipleRuns
  226.  
  227.    /*
  228.     * Initializations required for repeated program runs.
  229.     */
  230.  
  231.    pc = 0;                /* In lcode.c    */
  232.    nrecords = 0;            /* In lglob.c    */
  233.  
  234. #ifdef EvalTrace
  235.    colmno = 0;                /* In link.c    */
  236. #endif                    /* EvalTrace */
  237.  
  238.    lineno = 0;                /* In link.c    */
  239.    fatals = 0;                /* In link.c    */
  240.    nlflag = 0;                /* In llex.c    */
  241.    lstatics = 0;            /* In lsym.c    */
  242.    nfields = 0;                /* In lsym.c    */
  243. #endif                    /* MultipleRuns */
  244.  
  245.    /*
  246.     * Install "main" as a global variable in order to insure that it
  247.     *  is the first global variable.  iconx/start.s depends on main
  248.     *  being global number 0.
  249.     */
  250.    putglobal(instid("main"), F_Global, 0, 0);
  251.    }
  252.  
  253. #ifdef DeBugLinker
  254. /*
  255.  * dumplfiles - print the list of files to link.  Used for debugging only.
  256.  */
  257.  
  258. novalue dumplfiles()
  259.    {
  260.    struct lfile *p,*lfls;
  261.  
  262.    fprintf(stderr,"lfiles:\n");
  263.    lfls = llfiles;
  264.    while (p = getlfile(&lfls))
  265.        fprintf(stderr,"'%s'\n",p->lf_name);
  266.    fflush(stderr);
  267.    }
  268. #endif                    /* DeBugLinker */
  269.  
  270. /*
  271.  * alsolink - create an lfile structure for the named file and add it to the
  272.  *  end of the list of files (llfiles) to generate link instructions for.
  273.  */
  274. static char *pptr;
  275. novalue alsolink(name)
  276. char *name;
  277.    {
  278.    struct lfile *nlf, *p;
  279.    char file[256], ok;
  280.  
  281.    ok = 0;
  282.    if (canread(name)) {
  283.       ok++;
  284.       strcpy(file, name);
  285.       }
  286.    else {
  287.       /*
  288.        * Can't find name in current directory so try paths in
  289.        *   IPATH if there are any. (IPATH cannot override the
  290.        *   current-directory-first strategy so there is probably
  291.        *   no reason to initialize IPATH to the various current
  292.        *   directory markers as is done above, since this will
  293.        *   only result in a duplicate failed search. Note that
  294.        *   the access test which is done above in some systems
  295.        *   will have already caused ilink to exit if name is
  296.        *   not found in the current directory anyway so ipath
  297.        *   was never able to search other paths first in any case.)
  298.        */
  299.  
  300.  
  301.       pptr = ipath;
  302.  
  303.       while (trypath(name, file)) {
  304.          if (canread(file)) {
  305.             ok++;
  306.             break;
  307.             }
  308.          }
  309.       }
  310.  
  311.    if (!ok)
  312.      quitf("cannot resolve reference to file '%s'",name);
  313.  
  314.    nlf = alclfile(file);
  315.    if (llfiles == NULL) {
  316.       llfiles = nlf;
  317.       }
  318.    else {
  319.       p = llfiles;
  320.       while (p->lf_link != NULL) {
  321.         if (strcmp(p->lf_name,file) == 0)
  322.            return;
  323.         p = p->lf_link;
  324.         }
  325.       if (strcmp(p->lf_name,file) == 0)
  326.         return;
  327.       p->lf_link = nlf;
  328.       }
  329.    }
  330.  
  331. /*
  332.  * getlfile - return a pointer (p) to the lfile structure pointed at by lptr
  333.  *  and move lptr to the lfile structure that p points at.  That is, getlfile
  334.  *  returns a pointer to the current (wrt. lptr) lfile and advances lptr.
  335.  */
  336. struct lfile *getlfile(lptr)
  337. struct lfile **lptr;
  338.    {
  339.    struct lfile *p;
  340.  
  341.    if (*lptr == NULL)
  342.       return (struct lfile *)NULL;
  343.    else {
  344.       p = *lptr;
  345.       *lptr = p->lf_link;
  346.       return p;
  347.       }
  348.    }
  349.  
  350. /*
  351.  * canread - see if file can be read and be sure that it's just an
  352.  *  ordinary file.
  353.  */
  354. static int canread(file)
  355. char *file;
  356.    {
  357.  
  358. /*
  359.  * The following code is operating-system dependent [@lmem.03]. Check to see if
  360.  *  .u1 file can be read.
  361.  */
  362.  
  363. #if PORT
  364.    /* something is needed */
  365. Deliberate Syntax Error
  366. #endif                    /* PORT */
  367.  
  368. #if AMIGA
  369.    char lclname[MaxFileName];
  370.    if (access(makename(lclname,TargetDir,file,U1Suffix),4) == 0)
  371.       if (getfa(lclname) == -1)
  372.          return 1;
  373. #endif                    /* AMIGA */
  374.  
  375. #if ARM
  376.    {
  377.    FILE *f;
  378.    if ((f = fopen(file,ReadText)) != NULL) {
  379.       fclose(f);
  380.       return 1;
  381.       }
  382.    }
  383. #endif                    /* ARM */
  384.  
  385. #if ATARI_ST || HIGHC_386
  386.    {
  387.    FILE *f;
  388.    char lclname[MaxFileName];
  389.    if ((f = fopen(makename(lclname,TargetDir,file,U1Suffix), ReadText)) == NULL)
  390.       return 0;
  391.    else {
  392.       fclose(f);
  393.       return 1;
  394.       }
  395.    }
  396. #endif                    /* ATARI_ST || HIGHC_386 */
  397.  
  398. #if MACINTOSH
  399. #if MPW || LSC
  400.    {
  401.    FILE *f;
  402.    if ((f = fopen(file,ReadText)) != NULL) {
  403.       fclose(f);
  404.       return 1;
  405.       }
  406.    }
  407. #endif                    /* MPW || LSC */
  408. #endif                    /* MACINTOSH */
  409.  
  410. #if MSDOS
  411. #if MICROSOFT || TURBO
  412.    struct stat statb;
  413.    if (access(file,4) == 0) {
  414.       stat(file,&statb);
  415.       if (statb.st_mode & S_IFREG)
  416.          return 1;
  417.       }
  418. #else                    /* MICROSOFT || TURBO */
  419.    char lclname[MaxFileName];
  420.    if (access( makename(lclname,TargetDir,file,U1Suffix), 4 ) == 0 )
  421.       return 1;
  422. #endif                    /* MICROSOFT || TURBO */
  423. #endif                    /* MSDOS */
  424.  
  425. #if MVS || VM
  426. #if SASC
  427.    char lclname[MaxFileName];
  428.    if (access(makename(lclname,(char*)NULL,file,U1Suffix),R_OK) == 0)
  429.       return 1;
  430. #else                    /* SASC */
  431.    FILE *f;                     /* can't use access because it will */
  432.                                 /* accept LRECL, etc. */
  433.  
  434.    if ((f = fopen(file,"r")) != NULL {
  435.       fclose(f);
  436.       return 1;
  437.       }
  438. #endif                    /* SASC */
  439. #endif                    /* MVS || VM */
  440.  
  441. #if OS2
  442. #if MICROSOFT
  443.    struct stat statb;
  444.    if (access(file,4) == 0) {
  445.       stat(file,&statb);
  446.       if (statb.st_mode & S_IFREG)
  447.          return 1;
  448.       }
  449. #endif                    /* MICROSOFT || TURBO */
  450. #endif                    /* OS2 */
  451.  
  452. #if UNIX
  453.    struct stat statb;
  454.    if (access(file,4) == 0) {
  455.       stat(file,&statb);
  456.       if (statb.st_mode & S_IFREG)
  457.          return 1;
  458.       }
  459. #endif                    /* UNIX */
  460.  
  461. #if VMS
  462.    if (access(file,4) == 0)
  463.       return 1;
  464. #endif                    /* VMS */
  465.  
  466. /*
  467.  * End of operating-system specific code.
  468.  */
  469.  
  470.    return 0;
  471.    }
  472.  
  473.  
  474. /*
  475.  * trypath - form a file name in file by concatenating name onto the
  476.  *  next path element.
  477.  */
  478. static int trypath(name,file)
  479. char *name, *file;
  480.    {
  481.    char c;
  482.  
  483.    while (*pptr == ' ')
  484.       pptr++;
  485.    if (!*pptr)
  486.       return 0;
  487.    do {
  488.       c = (*file++ = *pptr++);
  489.       }
  490.       while (c != ' ' && c);
  491.    pptr--;
  492.    file--;
  493.  
  494. /*
  495.  * The following code is operating-system dependent [@lmem.04].  Append path
  496.  *  character.
  497.  */
  498.  
  499. #if PORT
  500.    /* nothing is needed */
  501. Deliberate Syntax Error
  502. #endif                    /* PORT */
  503.  
  504. #if AMIGA
  505.    file--;
  506.    switch (*file) {
  507.  
  508.       case ':':
  509.       case '/':
  510.                  file++;
  511.                  break;       /* add nothing, delimiter already there */
  512.       default:
  513.                  *file++ = '/';
  514.       }
  515. #endif                    /* AMIGA */
  516.  
  517. #if ARM || ATARI_ST || MACINTOSH || MVS || VM || VMS
  518.    /* nothing is needed */
  519. #endif                    /* ATARI_ST || MACINTOSH */
  520.  
  521. #if HIGHC_386
  522.    *file++ = '\\';
  523. #endif                    /* HIGHC_386 */
  524.  
  525. #if UNIX || MSDOS || OS2
  526.    *file++ = '/';            /* should check for delimiter */
  527. #endif                    /* UNIX || MSDOS || OS2 */
  528.  
  529. /*
  530.  * End of operating-system specific code.
  531.  */
  532.  
  533.    while (*file++ = *name++);
  534.    *file = 0;
  535.    return 1;
  536.    }
  537.  
  538. /*
  539.  * alclfile - allocate an lfile structure for the named file, fill
  540.  *  in the name and return a pointer to it.
  541.  */
  542. static struct lfile *alclfile(name)
  543. char *name;
  544.    {
  545.    struct lfile *p;
  546.  
  547.    p = (struct lfile *) alloc(sizeof(struct lfile));
  548.    p->lf_link = NULL;
  549.    p->lf_name = salloc(name);
  550.    return p;
  551.    }
  552.  
  553. #ifdef MultipleRuns
  554. /*
  555.  * freelfile - free memory of an lfile structure.
  556.  */
  557. static novalue freelfile(p)
  558. struct lfile *p;
  559.    {
  560.    free(p->lf_name);
  561.    free((char *) p);
  562.    }
  563. #endif                        /* MultipleRuns */
  564.  
  565. /*
  566.  * lmfree - free memory used by the linker
  567.  */
  568. novalue lmfree()
  569.    {
  570.    struct lfile *lf, *nlf;
  571.  
  572.    free((char *) lghash);   lghash = NULL;
  573.    free((char *) lihash);   lihash = NULL;
  574.    free((char *) lfhash);   lfhash = NULL;
  575.    free((char *) lltable);   lltable = NULL;
  576.    free((char *) lctable);   lctable = NULL;
  577.    free((char *) lftable);   lftable = NULL;
  578.    free((char *) lgtable);   lgtable = NULL;
  579.    free((char *) litable);   litable = NULL;
  580.    free((char *) lntable);   lntable = NULL;
  581.    free((char *) lrtable);   lrtable = NULL;
  582.    free((char *) lsspace);   lsspace = NULL;
  583.    free((char *) fnmtbl);   fnmtbl = NULL;
  584.    free((char *) labels);   labels = NULL;
  585.    free((char *) codep);   codep = NULL;
  586.  
  587. #ifdef MultipleRuns
  588.    for (lf = llfiles; lf != NULL; lf = nlf) {
  589.       nlf = lf->lf_link;
  590.       freelfile(lf);
  591.       }
  592.    llfiles = NULL;
  593.  
  594. #if MACINTOSH
  595. #if MPW
  596. /* #pragma unused(nlf,lf) */
  597. #endif                    /* MPW */
  598. #endif                    /* MACINTOSH */
  599. #endif                    /* MultipleRuns */
  600.  
  601.    }
  602.